/**
 * 
 * 
 *  
 *====================================================
 * 文件名称: BaseDaoImpl.java
 * 修订记录：
 * No    日期             作者(操作:具体内容)
 * 1.    Jul 30, 2009        
 *====================================================
 * 类描述：
 * 
 */
package com.devframe.sysbase.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

//import oracle.jdbc.OracleTypes;
//import oracle.jdbc.driver.OracleCallableStatement;

//import org.apache.commons.dbcp.DelegatingCallableStatement;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.devframe.sys.util.page.PageInfo;
import com.devframe.sysbase.dao.AbstractDao;
import com.devframe.sysbase.dao.BaseDao;


/**
 * <pre>
 * &lt;b&gt;&lt;font color=&quot;blue&quot;&gt;BaseDaoImpl&lt;/font&gt;&lt;/b&gt;
 * </pre>
 * 
 * <pre>
 * &lt;b&gt; --描述说明--&lt;/b&gt;
 * </pre>
 * <pre>
 *  DAO基类，方便操作HIBERNATE和JDBC。
 * 提供方便的分页查询，以及命名参数查询方式。
 * 存储过程调用封装
 * &lt;pre&gt;
 * &lt;b&gt;--样例--&lt;/b&gt;
 *   BaseDaoImpl obj = new BaseDaoImpl();
 *   obj.method();
 * &lt;/pre&gt;
 * JDK版本：JDK1.4
 * &#064;author  &lt;b&gt;&lt;/b&gt;
 * 
 */

public class BaseDaoImpl extends AbstractDao implements BaseDao {
   
    /**
     * jdbc SQL日志
     */
    protected static Logger logger = Logger.getLogger(BaseDaoImpl.class);

    public BaseDaoImpl() {
    }

    /**
     * Hibernate sessionFactory
     */
    private SessionFactory sessionFactory;

    /**
     * 返回一个新的session， 从SessionFactoryUtils取得当前线程的session
     * 
     * @return the active Session
     */
    public Session getSession() {
        return SessionFactoryUtils.getSession(sessionFactory, true);
    }

    /**
     * SessionFactory 注入方法
     * 
     * @param sessionFactory
     *            sessionFactory
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * getSessionFactory
     * 
     * @return sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    

    /**
     * 执行HQL查询语句返回列表
     * 
     * @param queryStr
     *            queryStr
     * @return List
     */
    public List queryForList(String queryStr) {
        return queryForList(queryStr, null);
    }

    /**
     * 执行HQL查询语句返回列表
     * 
     * @param queryStr
     *            queryStr
     * @param params
     *            params
     * @return List
     */
    public List queryForList(String queryStr, Map params) {
        try {
            Query query = this.getQuery(queryStr, params);
            return query.list();
        } catch (HibernateException e) {
            logger.error(queryStr);
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * hibernate 分页数据查询
     * 
     * @param hql
     *            需要执行的hql语句
     * @param params
     *            参数MAP 总记录数，为0表示第一页查询，会自动查询总记录数。
     *            自动计算总记录数只适用于简单查询，如对一个对象的查询或者没有分组汇总计算的查询或者记录量很小的查询。
     *            分组汇总查询在HQL中没法生成快速的总数查询语句，只能查询出全部记录计算总记录数，这在记录量大时会带来很大的性能问题。
     *            建议另行计算总数，可以采用更优化的方法进行计算，在查询中传入总记录数值，可以避免重复查询总记录数。
     * @param pageInfo
     *            分页参数:总记录数、分页记录数、当前页码
     * @return PageInfo
     */
    public PageInfo queryForPage(String hql, Map params, PageInfo pageInfo) {
        PageInfo page = pageInfo;
        if (page == null) {
            page = new PageInfo();
        }
        return queryForPage(hql, params, page.getTotalCount(), page.getPageSize(), page.getPageIndex(), page
            .getSortField(), page.getSortDirect());
    }

    /**
     * hibernate 分页查询：
     * 
     * 一般查询语句：如select a from tablea a where conditionExpr order by orderExpr
     * 生成的总数查询语句为 select count(*) from tablea a where conditionExpr
     * 分组汇总查询HQL语句没法生成总数查询语句(因为hql不支持在查询中用子查询)，
     * 只能查询全部记录得到记录数。性能很差应避免使用，此时应通过变通的方法先求出总数然后再进行分页查询。
     * 
     * @param hql
     *            查询hql,如果包含排序字段则用${sortField}宏表示
     * @param params
     *            查询参数
     * @param totalCount
     *            总记录数，为0时自动查询总记录数，否则不再查询总记录数
     * @param pageSize
     *            分页记录数
     * @param pageIndex
     *            页码
     * @return 分页数据
     * 
     */
    public PageInfo queryForPage(String hql, Map params, int totalCount, int pageSize, int pageIndex,
        String sortField, String sortDirect) {
        String hql1 = hql;
        if (sortField != null && !sortField.equals("") && hql.contains("${sortField}")) {
            String sortExpr = sortField + " " + (sortDirect == null ? "" : sortDirect);
            //如果排序字段中含有$符号，会出错
            sortExpr=sortExpr.replace("$", "\\$");
            hql1=hql.replaceAll("\\$\\{sortField\\}", sortExpr);
        }
        hql1 = sqlParse(new StringBuffer(hql1), params);
        PageInfo pageInfo = new PageInfo();
        pageInfo.setSortField(sortField);
        pageInfo.setSortDirect(sortDirect);
        try {
            if (pageIndex == 0) {
                pageInfo.setPageIndex(1);
            } else {
                pageInfo.setPageIndex(pageIndex);
            }
            pageInfo.setPageSize(pageSize);

            if (totalCount == 0) {// hql 查询总记录数处理，简单sql(含group by
                // 语句将会查询所有记录来求得总数)
                // hql = hql.replaceAll("FROM ", "from ");
                // hql = hql.replaceAll("FROM ", "from ");
                // hql = hql.replaceAll("GOUPR BY ", "group by ");
                // hql = hql.replaceAll("Group by ", "group by ");
                // hql = hql.replaceAll("Group By ", "group by ");
                Pattern p1 = Pattern.compile("from", Pattern.CASE_INSENSITIVE);
                hql1 = p1.matcher(hql1).replaceAll("from");

                Pattern p2 = Pattern.compile("[\\s]*group[\\s]*by *", Pattern.CASE_INSENSITIVE);
                hql1 = p2.matcher(hql1).replaceAll(" group by ");

                Pattern p4 = Pattern.compile("[\\s]* distinct[\\s] *", Pattern.CASE_INSENSITIVE);
                hql1 = p4.matcher(hql1).replaceAll(" distinct ");

                // Pattern p3 = Pattern.compile("[\\s]*order[\\s]*by[\\s\\S]*",
                // Pattern.CASE_INSENSITIVE);
                // hql = p3.matcher(hql).replaceAll("");

                String tSql = "select count(*) " + hql1.substring(hql1.indexOf("from"));
                if (hql1.indexOf("distinct ") > 0) {
                    tSql = hql1;
                }
                tSql = tSql.replaceAll("order by .*", "");
                if (hql1.lastIndexOf("group by ") > 0 || hql1.indexOf("distinct ") > 0) {
                    Query tQuery = this.getQuery(tSql, params);
                    pageInfo.setTotalCount(tQuery.list().size());
                } else {
                    Query tQuery = this.getQuery(tSql, params);
                    pageInfo.setTotalCount(Integer.valueOf(tQuery.list().get(0).toString()).intValue());
                }

            } else {
                pageInfo.setTotalCount(totalCount);
            }

            Query query = this.getQuery(hql1, params);
            if (pageInfo.getPageSize() != -1) {
                query.setFirstResult((pageInfo.getPageIndex() - 1) * pageInfo.getPageSize());
                query.setMaxResults(pageInfo.getPageSize());
            }
            pageInfo.setDataList(query.list());
            if (pageInfo.getPageSize() == -1) {// -1表示不分页
                pageInfo.setPageCount(1);
                pageInfo.setPageIndex(1);
                pageInfo.setTotalCount(pageInfo.getDataList().size());
            }
        } catch (HibernateException e) {
            logger.error(hql1);
            e.printStackTrace();
            throw e;
        }

        return pageInfo;
    }

    /**
     * 执行返回一条记录的查询,方便对单个对象查询以及总数合计类的查询
     * 
     * @param hql
     *            hql
     * @return Object
     * 
     */
    public Object queryForObject(String hql) {
        return queryForObject(hql, null);
    }

    /**
     * 执行返回一条记录的查询,方便对单个对象查询以及总数合计类的查询
     * 
     * @param hql
     *            hql语句
     * @param params
     *            Map存储的参数
     * @return Object
     */
    public Object queryForObject(String hql, Map params) {
        Object o = null;
        try {
            // Query.uniqueResult()
            List list = this.getQuery(hql, params).list();
            if (list.size() > 0) {
                o = list.get(0);
            }
        } catch (HibernateException e) {
            logger.error(hql);
            e.printStackTrace();
            throw e;
        }
        return o;
    }

    /**
     * 执行hql批量更新语句
     * 
     * @param hql
     *            sql
     * @param params
     *            参数，可以为null
     * @return 更新影响的记录数
     */
    public int executeUpdate(String hql, Map params) {
        Query query = this.getQuery(hql, params);
        return query.executeUpdate();
    }

    /**
     * 执行hql批量更新语句
     * 
     * @param hql
     *            sql
     * @return 更新影响的记录数
     */
    public int executeUpdate(String hql) {
        Query query = this.getQuery(hql);
        return query.executeUpdate();
    }

    /**
     * 通过命名参数执行JDBC语句查询列表的方法
     * 
     * @param queryStr
     *            查询SQL
     * @param params
     *            查询参数
     * @return List
     * 
     */
    public List sqlQueryForList(String queryStr, Map params) {
        try {
        	String sql = sqlParse(new StringBuffer(queryStr), params);
            SQLQuery sqlQuery = this.getSqlQuery(sql, params);
            sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
            return sqlQuery.list();
        } catch (HibernateException e) {
            logger.error(queryStr);
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 通过JDBC原生SQL查询列表，返回HashMap对象组成的列表
     * 
     * @param queryStr
     *            查询SQL
     * @return List
     * 
     */
    public List sqlQueryForList(String queryStr) {
        return sqlQueryForList(queryStr, null);
    }

    /**
     * 单记录查询,返回字段名为主键的MAP
     * 
     * @param queryStr
     *            查询sql
     * @return Map
     */
    public Map sqlQueryForMap(String queryStr) {
        return sqlQueryForMap(queryStr, null);
    }

    /**
     * 单记录查询,返回字段名为主键的MAP
     * 
     * @param queryStr
     *            查询sql
     * @param params
     *            查询参数
     * @return Map
     * 
     */
    public Map sqlQueryForMap(String queryStr, Map params) {
        List list = sqlQueryForList(queryStr, params);
        if (list != null && list.size() > 0) {
            return (Map) list.get(0);
        } else {
            return new HashMap();
        }
    }

    /**
     * 单值查询
     * 
     * @param queryStr
     *            查询sql
     * @return 字符串
     */
    public String sqlQueryForValue(String queryStr) {
        return sqlQueryForValue(queryStr, null);
    }

    /**
     * 单值查询
     * 
     * @param queryStr
     *            查询sql
     * @param params
     *            查询参数
     * @return 字符串
     * 
     */
    public String sqlQueryForValue(String queryStr, Map params) {
        Map map = sqlQueryForMap(queryStr, params);
        if (map != null && map.values().size() > 0) {
            Object value = map.values().iterator().next();
            if (value != null) {
                return value.toString();
            }
        }
        return null;
    }

    /**
     * 执行JDBC语句分页查询的方法
     * 
     * @param sql
     *            查询sql
     * @param totalCount
     *            总记录数
     * @param pageSize
     *            分页记录数
     * @param pageIndex
     *            页码
     * @return 查询结果对象分页列表
     * 
     */
    public PageInfo sqlQueryForPage(String sql, int totalCount, int pageSize, int pageIndex) {
        return sqlQueryForPage(sql, new HashMap(), totalCount, pageSize, pageIndex, null, null);
    }

    /**
     * @param sql
     *            查询sql
     * @param params
     *            查询参数
     * @param pageInfo
     *            分页条件
     * @return 查询结果对象分页列表
     * 
     */
    public PageInfo sqlQueryForPage(String sql, Map params, PageInfo pageInfo) {
        PageInfo page = pageInfo;
        if (page == null) {
            page = new PageInfo();
        }
        return sqlQueryForPage(sql, params, page.getTotalCount(), page.getPageSize(), page.getPageIndex(), page
            .getSortField(), page.getSortDirect());
    }

    /**
     * @param sql
     *            查询sql
     * @param pageInfo
     *            分页条件
     * @return 查询结果对象分页列表
     * 
     */
    public PageInfo sqlQueryForPage(String sql, PageInfo pageInfo) {
        PageInfo page = pageInfo;
        if (page == null) {
            page = new PageInfo();
        }
        return sqlQueryForPage(sql, new HashMap(), pageInfo);
    }

    /**
     * 执行JDBC语句分页查询的方法，参数使用命名参数方式传递，放在一个MAP对象中
     * 
     * @param sql
     *            查询sql
     * @param params
     *            查询参数
     * @param totalCount
     *            总记录数
     * @param pageSize
     *            分页记录数
     * @param pageIndex
     *            页码
     * @return 查询结果对象分页列表
     * 
     */
    public PageInfo sqlQueryForPage(String sql, Map params, int totalCount, int pageSize, int pageIndex,
        String sortField, String sortDirect) {
        if (sortField != null && !sortField.equals("") && sql.contains("${sortField}")) {
            String sortExpr = sortField + " " + (sortDirect == null ? "" : sortDirect);
            //如果排序字段中含有$符号，会出错
            sortExpr=sortExpr.replace("$", "\\$");
            sql=sql.replaceAll("\\$\\{sortField\\}", sortExpr);
        }
        String sqlStr = sqlParse(new StringBuffer(sql), params);
        PageInfo pageInfo = new PageInfo(pageSize, pageIndex, totalCount);
        pageInfo.setSortField(sortField);
        pageInfo.setSortDirect(sortDirect);
        try {
            if (totalCount == 0) {
                String temp = sqlStr.replaceAll("ORDER BY.*", "");
                temp = temp.replaceAll("order by.*", "");
                String tSql = "select count(*) TOTALCOUNT from (" + temp + ") T";
                pageInfo.setTotalCount(Integer.parseInt(((Map) sqlQueryForMap(tSql, params)).get("TOTALCOUNT")
                    .toString()));
            } else {
                pageInfo.setTotalCount(totalCount);
            }
            if (pageIndex == 0) {
                pageInfo.setPageIndex(1);
            } else {
                pageInfo.setPageIndex(pageIndex);
            }
            pageInfo.setPageSize(pageSize);

            SQLQuery sqlQuery = this.getSqlQuery(sqlStr, params);
            if (pageInfo.getPageSize() != -1) {
                sqlQuery.setFirstResult((pageInfo.getPageIndex() - 1) * pageInfo.getPageSize());
                sqlQuery.setMaxResults(pageInfo.getPageSize());
            }
            sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
            pageInfo.setDataList(sqlQuery.list());
            if (pageInfo.getPageSize() == -1) {
                pageInfo.setPageCount(1);
                pageInfo.setPageIndex(1);
                pageInfo.setTotalCount(pageInfo.getDataList().size());
            }
        } catch (HibernateException e) {
            logger.error(sql);
            e.printStackTrace();
            throw e;
        }
        return pageInfo;
    }

    /**
     * getSequenceValue 获取序列号的值
     * 
     * @param sequenceName
     * @return 序列号的下一个值
     * 
     */
    public BigInteger getSequenceValue(String sequenceName) {
        String sql = "SELECT " + sequenceName + ".NEXTVAL FROM DUAL";
        return new BigInteger(this.sqlQueryForValue(sql));
    }

    /**
     * 执行JDBC SQL更新语句,也可以执行不需要返回值的过程
     * 
     * @param sql
     *            sql
     * @param params
     *            参数，可以为null
     * @return 更新影响的记录数
     */
    public int executeSqlUpdate(String sql, Map params) {
        Query query = this.getSqlQuery(sql, params);
        return query.executeUpdate();
    }

    /**
     * 执行JDBC SQL更新语句,也可以执行不需要返回值的过程
     * 
     * @param sql
     *            sql
     * @return 更新影响的记录数
     */
    public int executeSqlUpdate(String sql) {
        return executeSqlUpdate(sql, null);
    }

    /**
     * 根据对象类型和ID查询对象
     * 
     * @param refClass
     *            Hibernate映射类
     * @param key
     *            主键值
     * @return Hibernate对象
     * 
     */
    public Object get(Class refClass, Serializable key) {
        Session s = getSession();
        return s.get(refClass, key);
    }

    /**
     * 
     * 根据对象类型和ID 用load方法查找对象
     * 
     * @param refClass
     *            Hibernate映射类
     * @param key
     *            主键值
     * @return Hibernate对象
     * 
     */
    public Object load(Class refClass, Serializable key) {
        Session s = getSession();
        return s.load(refClass, key);
    }

    /**
     * 查询一个对象的所有记录
     * 
     * @param refClass
     *            Hibernate映射类
     * @return List所有对象列表
     * 
     */
    public List findAll(Class refClass) {
        Session s = getSession();
        Criteria crit = s.createCriteria(refClass);
        return crit.list();
    }

    /**
     * 
     * 从配置文件中获取命名sql对象
     * 
     * @param queryName
     *            the name of a query defined externally
     * @return Query
     */
    public Query getNamedQuery(String queryName) {
        Session s = getSession();
        Query q = s.getNamedQuery(queryName);
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return q;
    }

    /**
     * getNamedQuerySql 从配置文件中获取命名sql对象的SQL，用于将SQL独立在java类之外。
     * 
     * @param name
     *            命名脚本名字
     * @return 命名脚本字符串
     * 
     */
    public String getNamedQuerySql(String name) {
        Session s = getSession();
        Query q = s.getNamedQuery(name);
        return q.getQueryString();
    }

    /**
     * 执行配置文件中的命名sql并指定唯一参数 SQL中通过?代表参数
     * 
     * @param name
     *            the name of a query defined externally
     * @param param
     *            the only parameter to set
     * @return List
     */
    public List namedQueryForList(String name, Serializable param) {
        Session s = getSession();
        Query q = s.getNamedQuery(name);
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        q.setParameter(1, param);
        return q.list();
    }

    /**
     * 执行配置文件中的命名sql并指定参数数组 SQL中通过?代表参数
     * 
     * @param name
     *            the name of a query defined externally
     * @param params
     *            the parameter array
     * @return List
     */
    public List namedQueryForList(String name, Serializable[] params) {
        Session s = getSession();
        Query q = s.getNamedQuery(name);
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if (null != params) {
            for (int i = 0; i < params.length; i++) {
                q.setParameter(i + 1, params[i]);
            }
        }
        return q.list();
    }

    /**
     * 执行配置文件中的命名sql并指定参数Map SQL中通过:paramName形式对参数进行命名
     * 
     * @param name
     *            the name of a query defined externally
     * @param params
     *            the parameter Map
     * @return Query
     */
    public List namedQueryForList(String name, Map params) {
        Session s = getSession();
        Query q = s.getNamedQuery(name);
        q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        if (null != params) {
            for (Iterator i = params.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                q.setParameter((String) entry.getKey(), entry.getValue());
            }
        }
        return q.list();
    }

    /**
     * create a query. 通过hql创建Query对象
     * 
     * @param hql
     *            a query expressed in Hibernate's query language
     * @return Query
     */
    public Query getQuery(String hql) {
        Session s = getSession();
        return s.createQuery(hql);
    }

    /**
     * 通过hql创建Query对象，指定唯一参数
     * 
     * @param hql
     *            a query expressed in Hibernate's query language
     * @param param
     *            the first parameter to set
     * @return Query
     */
    public Query getQuery(String hql, Serializable param) {
        Query q = getQuery(hql);
        q.setParameter(1, param);
        return q;
    }

    /**
     * Create a query. 通过hql创建Query对象，指定参数数组
     * 
     * @param hql
     *            a query expressed in Hibernate's query language
     * @param params
     *            the parameter array
     * @return Query
     */
    public Query getQuery(String hql, Serializable[] params) {
        Session s = null;
        Query q = getQuery(hql, s);
        if (null != params) {
            for (int i = 0; i < params.length; i++) {
                q.setParameter(i + 1, params[i]);
            }
        }
        return q;
    }

    /**
     * Create a query. 通过hql创建Query对象，指定参数Map
     * 加强版的getQuery,可以处理in(:paramName)格式的参数，
     * 此时参数用实现iterator接口或者Collection接口的类型传入，如List;也可以用数组传入，如String[]
     * 
     * @param hql
     *            hibernate query statement
     * @param params
     *            参数Map
     * @return Query
     * 
     */
    public Query getQuery(String hql, Map params) {
        logger.debug(hql);
        String hqlStr = sqlParse(new StringBuffer(hql), params);
        Query q = null;// = getQuery(queryStr, s);
        if (null != params) {
            Map newParams = new HashMap();
            newParams.putAll(params);
            for (Iterator i = params.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                Object value = entry.getValue();
                /**
                 * 不兼容1.4 if (entry.getValue() instanceof Iterable) {
                 */
                if (value instanceof Iterator || value instanceof Collection) {
                    StringBuffer sb = new StringBuffer();
                    String paramName = (String) entry.getKey();
                    // Iterator it = (( Iterable ) entry.getValue()).Iterator();

                    Iterator it = null;
                    if (value instanceof Iterator) {
                        it = (Iterator) value;
                    } else {
                        it = ((Collection) value).iterator();
                    }
                    int idx = 0;
                    if (it.hasNext()) {
                        while (it.hasNext()) {
                            if (idx > 0) {
                                sb.append(",");
                            }
                            sb.append(":").append(paramName).append("_").append(idx);
                            newParams.put(paramName + "_" + idx, it.next());
                            idx++;
                        }
                        hqlStr = hqlStr.replaceAll(":" + paramName, sb.toString());
                        newParams.remove(paramName);
                    } else {
                        newParams.put(entry.getKey(), null);
                    }
                } else if (entry.getValue() != null && entry.getValue().getClass().isArray()) {
                    StringBuffer sb = new StringBuffer();
                    String paramName = (String) entry.getKey();
                    int length = Array.getLength(entry.getValue());
                    for (int j = 0; j < length; j++) {
                        Object paramItem = Array.get(entry.getValue(), j);
                        if (j > 0) {
                            sb.append(",");
                        }
                        sb.append(":").append(paramName).append("_").append(j);
                        newParams.put(paramName + "_" + j, paramItem);
                    }
                    hqlStr = hqlStr.replaceAll(":" + paramName, sb.toString());
                    newParams.remove(paramName);
                }
            }
            q = getQuery(hqlStr);
            for (Iterator i = newParams.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                q.setParameter((String) entry.getKey(), entry.getValue());
            }
        } else {
            q = getQuery(hqlStr);
        }
        return q;
    }

    /**
     * 加强版的getSQLQuery,可以处理in(:paramName)格式的参数，
     * 此时参数用实现iterator接口的类型传入，如List;也可以用数组传入，如String[]
     * 
     * @param sql
     *            查询sql
     * @param params
     *            查询参数Map
     * @return SQLQuery
     * 
     * 
     */
    protected SQLQuery getSqlQuery(String sql, Map params) {
        logger.debug("getSqlQuery:"+sql);
        //String queryStr = sqlParse(new StringBuffer(sql), params);
        String queryStr = sql;
        SQLQuery q = null;// = getQuery(queryStr, s);
        if (null != params) {
            Map newParams = new HashMap();
            newParams.putAll(params);
            for (Iterator i = params.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                /**
                 * Iterable不能用于JDK 1.4
                 */
                Object value = entry.getValue();
                if (value instanceof Iterator || value instanceof Collection) {
                    StringBuffer sb = new StringBuffer();
                    String paramName = (String) entry.getKey();
                    Iterator it = null;
                    if (value instanceof Iterator) {
                        it = (Iterator) value;
                    } else {
                        it = ((Collection) value).iterator();
                    }
                    int idx = 0;
                    if (it.hasNext()) {
                        while (it.hasNext()) {
                            if (idx > 0) {
                                sb.append(",");
                            }
                            sb.append(":").append(paramName).append("_").append(idx);
                            newParams.put(paramName + "_" + idx, it.next());
                            idx++;
                        }
                        queryStr = queryStr.replaceAll(":" + paramName, sb.toString());
                        newParams.remove(paramName);
                    } else {
                        newParams.put(entry.getKey(), null);
                    }

                } else if (entry.getValue() != null && entry.getValue().getClass().isArray()) {
                    StringBuffer sb = new StringBuffer();
                    String paramName = (String) entry.getKey();
                    int length = Array.getLength(entry.getValue());
                    for (int j = 0; j < length; j++) {
                        Object paramItem = Array.get(entry.getValue(), j);
                        if (j > 0) {
                            sb.append(",");
                        }
                        sb.append(":").append(paramName).append("_").append(j);
                        newParams.put(paramName + "_" + j, paramItem);
                    }
                    queryStr = queryStr.replaceAll(":" + paramName, sb.toString());
                    newParams.remove(paramName);
                }
            }
            q = this.getSession().createSQLQuery(queryStr);
            for (Iterator i = newParams.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                q.setParameter((String) entry.getKey(), entry.getValue());
            }
        } else {
            q = this.getSession().createSQLQuery(queryStr);
        }
        return q;
    }

    /**
     * Hibernate 保存新增对象
     * 
     * @param obj
     *            新增对象
     * @return 主键值
     * 
     */
    public Serializable save(final Object obj) {
        Session session = getSession();
        return session.save(obj);
    }

    /**
     * Hibernate 批量保存新增对象 save
     * 
     * @param objs
     *            新增对象集合
     * @return 记录数
     * 
     */
    public int save(final Collection objs) {
        Session session = getSession();
        if (objs != null) {
            Iterator it = objs.iterator();
            while (it.hasNext()) {
                session.save(it.next());
            }
        }
        return objs.size();
    }

    /**
     * Hibernate 保存对象修改
     * 
     * @param obj
     *            修改对象
     * 
     */
    public void update(final Object obj) {
        Session session = getSession();
        session.update(obj);
    }

    /**
     * Hibernate 批量保存对象修改
     * 
     * @param objs
     *            修改对象集合
     * 
     */
    public void update(final Collection objs) {
        Session session = getSession();
        if (objs != null) {
            Iterator it = objs.iterator();
            while (it.hasNext()) {
                session.update(it.next());
            }
        }
    }

    /**
     * Hibernate 删除query查询的所有记录
     * 
     * @param query
     *            Query对象
     * @return 删除记录数
     */
    public int delete(final Query query) {
        Session s = getSession();
        List list = query.list();
        for (Iterator i = list.iterator(); i.hasNext();) {
            s.delete(i.next());
        }
        return list.size();
    }

    /**
     * Hibernate 删除对象
     * 
     * @param obj
     *            要删除的对象
     * 
     */
    public void delete(final Object obj) {
        Session session = getSession();
        session.delete(obj);
    }

    /**
     * Hibernate 批量删除
     * 
     * @param objs
     *            要删除的记录集合
     * 
     */
    public void delete(final Collection objs) {
        Session session = getSession();
        if (objs != null) {
            Iterator it = objs.iterator();
            while (it.hasNext()) {
                session.delete(it.next());
            }
        }
    }

    /**
     * delete 批量删除
     * 
     * @param refClass
     *            Po类
     * @param keys
     *            主键数组
     * 
     */
    public void delete(Class refClass, Serializable[] keys) {
        if (keys != null) {
            for (int i = 0; i < keys.length; i++) {
                Object obj = this.get(refClass, keys[i]);
                this.delete(obj);
            }
        }

    }

    /**
     * Hibernate 刷新对象状态
     * 
     * @param obj
     *            要刷新对象
     */
    public void refresh(Object obj) {
        Session s = this.getSession();
        s.refresh(obj);
    }

//    /**
//     * executeJDBCFunc 简单函数调用，不支持通过out参数返回值。
//     * 
//     * @param funcName
//     *            函数名,可以只写函数名
//     * @param inParams
//     *            输入参数
//     * @param returnType
//     *            返回值类型
//     * @return 返回值
//     * @throws Exception
//     *             Exception
//     * 
//     */
//    public Object executeJDBCFunc(String funcName, Object[] inParams, int returnType) throws Exception {
//        Object result = null;
//        Connection conn = null;
//        CallableStatement proc = null;
//        logger.debug(funcName);
//        String execFunc = funcName;
//        if (!execFunc.startsWith("{")) {
//            execFunc = "{? = call " + funcName + "(";
//            for (int i = 0; i < inParams.length; i++) {
//                if (i > 0) {
//                    execFunc += ",";
//                }
//                execFunc += "?";
//            }
//            execFunc += ")}";
//        }
//        try {
//            /**
//             * TODO 这句写法被dprecate了，换为openStatelessSession conn =
//             * getSession().connection(); conn =
//             * sessionFactory.openStatelessSession().connection();
//             * 但是openStatelessSession会忽略缓存，即未提交的内容。因此会出现问题。还是先用吧
//             */
//            conn = getSession().connection();
//            conn.setAutoCommit(false);
//            proc = conn.prepareCall(execFunc);
//            proc.registerOutParameter(1, returnType);
//            int inParamCount = 0;
//            if (inParams != null) {
//                inParamCount = inParams.length;
//                for (int i = 0; i < inParamCount; i++) {
//                    proc.setObject(i + 2, inParams[i]);
//                }
//            }
//
//            proc.execute();
//
//            // 如果返回参数为结果集则进行封装
//            int pType = returnType;
//
//            if (pType == OracleTypes.CURSOR || pType == java.sql.Types.STRUCT) {
//                List resultList = new ArrayList();
//                CallableStatement stmt = proc;
//                if (proc instanceof org.apache.commons.dbcp.DelegatingCallableStatement) {
//                    DelegatingCallableStatement delgate = (DelegatingCallableStatement) proc;
//                    stmt = (CallableStatement) delgate.getDelegate();
//                }
//                ResultSet rs = ((OracleCallableStatement) stmt).getCursor(0);
//                // ResultSet rs =
//                // ((CallableStatement)proc).getResultSet();
//                while (rs != null && rs.next()) {
//                    Map rowMap = new LinkedHashMap();
//                    int colCount = rs.getMetaData().getColumnCount();
//                    for (int j = 0; j < colCount; j++) {
//                        rowMap.put(rs.getMetaData().getColumnName(j + 1), rs.getObject(j + 1));
//                    }
//                    resultList.add(rowMap);
//                }
//                rs.close();
//                result = resultList;
//            } else {
//                result = proc.getObject(1);
//            }
//
//        } catch (Exception he) {
//            logger.error("执行函数" + funcName + "出错：" + he.getLocalizedMessage());
//            he.printStackTrace();
//            throw he;
//        } finally {
//            try {
//                if (proc != null) {
//                    proc.close();
//                }
//            } catch (Exception ex) {
//                ex.printStackTrace();
//                throw ex;
//            }
//        }
//        return result;
//    }
//
//    /**
//     * 执行存储过程 示例： Object inParams = new Object[2]; inParams[0] = value1;
//     * inParams[1] = value2; int[] outParamTypes = new int[2]; outParamTypes[0] =
//     * java.sql.Types.NUMERIC; outParamTypes[1] = java.sql.Types.NUMERIC;
//     * 
//     * Map result = baseDao.executeJDBCProc("{call
//     * procName(?,?,?,?)}",inParams,outParamTypes); Object result0 =
//     * result.get(0); Object result1 = result.get(1);
//     * 
//     * @param procName
//     *            存储过程调用语句
//     * @param inParams
//     *            key 为参数索引，从1开始。value为参数值
//     * @param outParamTypes
//     *            为返回值类型数组
//     * @return 返回参数， key为返回值顺序号，从0开始 value为过程返回值，如果返回值为结果集则封装成HashMap组成的List
//     * @throws Exception
//     *             Exception
//     */
//    public Map executeJDBCProc(String procName, Object[] inParams, int[] outParamTypes) throws Exception {
//        Map result = new LinkedHashMap();
//        Connection conn = null;
//        CallableStatement proc = null;
//        logger.debug(procName);
//        try {
//            /**
//             * 这句写法被dprecate了，换为openStatelessSession conn =
//             * getSession().connection(); conn =
//             * sessionFactory.openStatelessSession().connection();
//             * 但是openStatelessSession会忽略缓存，即未提交的内容。因此会出现问题。还是先用吧
//             */
//            conn = getSession().connection();
//            conn.setAutoCommit(false);
//            proc = conn.prepareCall(procName);
//            int inParamCount = 0;
//            if (inParams != null) {
//                inParamCount = inParams.length;
//                for (int i = 0; i < inParamCount; i++) {
//                    proc.setObject(i + 1, inParams[i]);
//                }
//            }
//
//            int outParamCount = 0;
//            if (outParamTypes != null) {
//                outParamCount = outParamTypes.length;
//                for (int i = 0; i < outParamCount; i++) {
//                    proc.registerOutParameter(inParamCount + i + 1, outParamTypes[i]);
//                }
//            }
//
//            proc.execute();
//
//            // trans.commit();
//
//            if (outParamTypes != null) {
//                for (int i = 0; i < outParamCount; i++) {
//                    int pIndex = inParamCount + i + 1;
//                    // 如果返回参数为结果集则进行封装
//                    int pType = outParamTypes[i];
//
//                    if (pType == OracleTypes.CURSOR || pType == java.sql.Types.STRUCT) {
//                        List resultList = new ArrayList();
//                        CallableStatement stmt = proc;
//                        if (proc instanceof org.apache.commons.dbcp.DelegatingCallableStatement) {
//                            DelegatingCallableStatement delgate = (DelegatingCallableStatement) proc;
//                            stmt = (CallableStatement) delgate.getDelegate();
//                        }
//                        ResultSet rs = ((OracleCallableStatement) stmt).getCursor(pIndex);
//                        // ResultSet rs =
//                        // ((CallableStatement)proc).getResultSet();
//                        while (rs != null && rs.next()) {
//                            Map rowMap = new LinkedHashMap();
//                            int colCount = rs.getMetaData().getColumnCount();
//                            for (int j = 0; j < colCount; j++) {
//                                rowMap.put(rs.getMetaData().getColumnName(j + 1), rs.getObject(j + 1));
//                            }
//                            resultList.add(rowMap);
//                        }
//                        rs.close();
//                        result.put(new Integer(i), resultList);
//                    } else {
//                        result.put(new Integer(i), proc.getObject(pIndex));
//                    }
//                }
//            }
//
//        } catch (Exception he) {
//            logger.error(procName);
//            he.printStackTrace();
//            throw he;
//        } finally {
//            try {
//                if (proc != null) {
//                    proc.close();
//                }
//            } catch (Exception ex) {
//                ex.printStackTrace();
//                throw ex;
//            }
//        }
//        return result;
//    }
//
//    /**
//     * 2011-11-30 重载前一个方法,增加输入参数类型信息,防止特定WAS出现问题
//     * @param procName
//     * @param inParams
//     * @param inTypes
//     * @param outParamTypes
//     * @return
//     * @throws Exception
//     */
//    public Map executeJDBCProc(String procName, Object[] inParams,int[]inTypes, int[] outParamTypes) throws Exception{
//    	
//        Map result = new LinkedHashMap();
//        Connection conn = null;
//        CallableStatement proc = null;
//        logger.debug(procName);
//        try {
//
//            conn = getSession().connection();
//            conn.setAutoCommit(false);
//            proc = conn.prepareCall(procName);
//            int inParamCount = 0;
//            if (inParams != null) {
//                inParamCount = inParams.length;
//                for (int i = 0; i < inParamCount; i++) {
//                	 if(inParams[i]!=null){
//                		proc.setObject(i + 1, inParams[i]);
//                	 }else{
//                		proc.setNull(i + 1, inTypes[i]);
//                	 }
//                     
//                }
//            }
//
//            int outParamCount = 0;
//            if (outParamTypes != null) {
//                outParamCount = outParamTypes.length;
//                for (int i = 0; i < outParamCount; i++) {
//                    proc.registerOutParameter(inParamCount + i + 1, outParamTypes[i]);
//                }
//            }
//
//            proc.execute();
//
//            // trans.commit();
//
//            if (outParamTypes != null) {
//                for (int i = 0; i < outParamCount; i++) {
//                    int pIndex = inParamCount + i + 1;
//                    // 如果返回参数为结果集则进行封装
//                    int pType = outParamTypes[i];
//
//                    if (pType == OracleTypes.CURSOR || pType == java.sql.Types.STRUCT) {
//                        List resultList = new ArrayList();
//                        CallableStatement stmt = proc;
//                        if (proc instanceof org.apache.commons.dbcp.DelegatingCallableStatement) {
//                            DelegatingCallableStatement delgate = (DelegatingCallableStatement) proc;
//                            stmt = (CallableStatement) delgate.getDelegate();
//                        }
//                        ResultSet rs = ((OracleCallableStatement) stmt).getCursor(pIndex);
//                        // ResultSet rs =
//                        // ((CallableStatement)proc).getResultSet();
//                        while (rs != null && rs.next()) {
//                            Map rowMap = new LinkedHashMap();
//                            int colCount = rs.getMetaData().getColumnCount();
//                            for (int j = 0; j < colCount; j++) {
//                                rowMap.put(rs.getMetaData().getColumnName(j + 1), rs.getObject(j + 1));
//                            }
//                            resultList.add(rowMap);
//                        }
//                        rs.close();
//                        result.put(new Integer(i), resultList);
//                    } else {
//                        result.put(new Integer(i), proc.getObject(pIndex));
//                    }
//                }
//            }
//
//        } catch (Exception he) {
//            logger.error(procName);
//            he.printStackTrace();
//            throw he;
//        } finally {
//            try {
//                if (proc != null) {
//                    proc.close();
//                }
//            } catch (Exception ex) {
//                ex.printStackTrace();
//                throw ex;
//            }
//        }
//        return result;
//    }
//    /**
//     * 常用过程调用， 返回参数为code,message两个 返回Map中代码为code,消息为message
//     * 
//     * @param procName
//     *            存储过程
//     * @param inParams
//     *            传入参数
//     * @return 返回存储过程返回信息
//     * @throws Exception
//     *             Exception
//     * 
//     */
//    public Map executeNormalJDBCProc(String procName, Object[] inParams) throws Exception {
//        int[] outParamTypes = new int[] { java.sql.Types.NUMERIC, java.sql.Types.VARCHAR };
//        int pIndex = 1;
//        if (inParams != null) {
//            pIndex += inParams.length;
//        }
//        Map result = executeJDBCProc(procName, inParams, outParamTypes);
//        if (result.get(new Integer(0)) != null) {
//            result.put("code", result.get(new Integer(pIndex)));
//        }
//        if (result.get(new Integer(1)) != null) {
//            result.put("message", result.get(new Integer(pIndex + 1)));
//        }
//        return result;
//    }

    /**
     * main
     * 
     * @param args
     *            args
     * 
     */
    public static void main(String[] args) {
        String sqlTest = "select * from table1 order by ${sortField}";
        logger.info(sqlTest.replaceAll("\\$\\{sortField\\}", "\\$AAA"));
        /**
        
        BaseDaoImpl dao = new BaseDaoImpl();
        String sql1 = "from TMdServer a " + "/~ where a.code like :keyWord  " + "or a.name like :keyWord ~/";
        StringBuffer buffer1 = new StringBuffer(sql1);
        Map params1 = new HashMap();
        params1.put("keyWord", null);
        logger.info("参数:" + params1);
        dao.paramSqlParse(buffer1, params1);
        logger.info("解析后SQL:" + buffer1);

        String sqlStr = "select * from tab where 1=1" + "/~ and tname like :tname||'%' ~/"
            + "/~ and tabtype = :tabtype~/ " + "order by ${orderField1 },${orderField2 }";
        // 参数语法解析测试
        logger.info("根据参数构造SQL语法解析测试");
        StringBuffer sql = new StringBuffer(sqlStr);
        logger.info("原始SQL:" + sql);
        Map params = new HashMap();
        logger.info("参数:" + params);
        dao.paramSqlParse(sql, params);
        logger.info("解析后SQL:" + sql);

        sql = new StringBuffer(sqlStr);
        logger.info("原始SQL:" + sql);
        params.put("tname", "T_SYS");
        logger.info("参数:" + params);
        dao.paramSqlParse(sql, params);
        logger.info("解析后SQL:" + sql);

        sql = new StringBuffer(sqlStr);
        logger.info("原始SQL:" + sql);
        params.put("tabtype", "table");
        logger.info("参数:" + params);
        dao.paramSqlParse(sql, params);
        logger.info("解析后SQL:" + sql);
        logger.info("错误SQL测试");
        // 错误SQL测试1
        try {
            sql = new StringBuffer("select * from tab where 1=1 " + "/~ and tname like :tname   "
                + "/~ and tabtype = :tabtype ~/");
            logger.info("原始SQL:" + sql);
            dao.paramSqlParse(sql, params);
            logger.info("参数:" + params);
            logger.info("解析后SQL:" + sql);
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        // 错误SQL测试2
        try {
            sql = new StringBuffer("select * from tab where 1=1 " + "/~ and tname like :tname ~/  "
                + "/~ and tabtype = :tabtype ");
            logger.info("原始SQL:" + sql);
            dao.paramSqlParse(sql, params);
            logger.info("参数:" + params);
            logger.info("解析后SQL:" + sql);
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        // 错误SQL测试3
        try {
            sql = new StringBuffer(
                "select * from tab where 1=1 /~ and tname like :tname ~/  /~ and tabtype = 'table' ~/");
            dao.paramSqlParse(sql, params);
            logger.info(sql);
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        // 宏替换测试
        logger.info("宏替换测试");
        sql = new StringBuffer(sqlStr);
        logger.info("原始SQL:" + sql);
        logger.info("参数:" + params);
        params.put("orderField1", "tname");
        params.put("orderField2", "tabtype");
        dao.replaceMacro(sql, params);
        logger.info("解析后SQL:" + sql);

        // 综合解析
        logger.info("综合解析");
        params.put("orderField1", "tname");
        params.put("orderField2", "tabtype");
        sql = new StringBuffer(sqlStr);
        logger.info("原始SQL:" + sql);
        logger.info("参数:" + params);
        dao.sqlParse(sql, params);
        logger.info("解析后SQL:" + sql);
        // 速度测试
        long t1 = System.currentTimeMillis();
        for (int i = 0; i < 500000; i++) {
            sql = new StringBuffer(sqlStr);
            dao.paramSqlParse(sql, params);
        }
        logger.info("执行500000次条件语法解析耗时：" + (System.currentTimeMillis() - t1) + "毫秒");
        // 宏替换解析测试
        t1 = System.currentTimeMillis();
        for (int i = 0; i < 500000; i++) {
            params.put("orderField1", "tname");
            params.put("orderField2", "tabtype");
            sql = new StringBuffer(sqlStr);
            dao.replaceMacro(sql, params);
        }
        logger.info("宏替换解析执行500000次解析耗时：" + (System.currentTimeMillis() - t1) + "毫秒");
        // 整体解析测试，包含宏替换
        t1 = System.currentTimeMillis();
        for (int i = 0; i < 500000; i++) {
            sql = new StringBuffer(sqlStr);
            params.put("orderField1", "tname");
            params.put("orderField2", "tabtype");
            dao.sqlParse(sql, params);
        }
        logger.info("整体解析执行500000次解析耗时：" + (System.currentTimeMillis() - t1) + "毫秒");
        */
    }

//	public Date getOracleCurrentTime() {
//		// TODO Auto-generated method stub
//		Map map=this.sqlQueryForMap("SELECT SYSDATE FROM DUAL");
//		return (Date)map.get("SYSDATE");
//	}

//	public String getOracleCurrentTimeString(String format) {
//		// TODO Auto-generated method stub
//		Date date=this.getOracleCurrentTime();
//		SimpleDateFormat sdf=new SimpleDateFormat(format);
//		return sdf.format(date);
//	}

	public String getOracleCurrentTimeString() {
		// TODO Auto-generated method stub
        Map map=this.sqlQueryForMap("SELECT TO_CHAR(SYSDATE,'YYYYMMDDHH24MiSS') SYS_TIME FROM DUAL");
		return String.valueOf(map.get("SYS_TIME"));
	}

}